#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

namespace dew
{
	template<class T>
	struct ListNode
	{
		ListNode<T>* next;
		ListNode<T>* prev;
		T Date;

		ListNode(const T& x = T()) :next(nullptr), prev(nullptr), Date(x) {}
	};

	template<class T,class Ref,class Ptr>
	struct _list_iterator
	{
		typedef ListNode<T> Node;
		typedef _list_iterator<T, Ref, Ptr> self;
		Node* _node;

		_list_iterator(Node* node) :_node(node) {}

		self& operator++()
		{
			_node = _node->next;
			return *this;
		}

		self operator++(int)
		{
			self tmp(*this);
			_node = _node->next;
			return tmp;
		}

		self& operator--()
		{
			_node = _node->prev;
			return *this;
		}

		self operator--(int)
		{
			self tmp(*this);
			_node = _node->prev;
			return tmp;
		}

		Ref operator*()
		{
			return _node->Date;
		}

		Ptr operator->()
		{
			return &_node->Date;
		}

		bool operator!=(const self& s)
		{
			return _node != s._node;
		}

		bool operator==(const self& s)
		{
			return _node == s._node;
		}
	};


	//template<class T>
	//struct _list_const_iterator
	//{
	//	typedef ListNode<T> Node;
	//	typedef _list_const_iterator self;
	//	Node* _node;

	//	_list_const_iterator(Node* node) :_node(node) {}

	//	self& operator++()
	//	{
	//		_node = _node->next;
	//		return *this;
	//	}

	//	self operator++(int)
	//	{
	//		self tmp(*this);
	//		_node = _node->next;
	//		return tmp;
	//	}

	//	self& operator--()
	//	{
	//		_node = _node->prev;
	//		return *this;
	//	}

	//	self operator--(int)
	//	{
	//		self tmp(*this);
	//		_node = _node->prev;
	//		return tmp;
	//	}

	//	const T& operator*()
	//	{
	//		return _node->Date;
	//	}

	//	bool operator!=(const self& s)
	//	{
	//		return _node != s._node;
	//	}

	//	bool operator==(const self& s)
	//	{
	//		return _node == s._node;
	//	}
	//};

	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:

		typedef _list_iterator<T,  T&,T*> iterator;
		typedef _list_iterator<T,const T&,const T*> const_iterator;

		iterator begin()
		{
			//return iterator(_head->next);
			return _head->next;
		}

		iterator end()
		{
			//return iterator(_head->next);
			return _head;
		}

		const_iterator begin() const
		{
			//return iterator(_head->next);
			return _head->next;
		}

		const_iterator end() const
		{
			//return iterator(_head->next);
			return _head;
		}


		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}

		void empty_init()
		{
			_head = new Node;
			_head->next = _head;
			_head->prev = _head;
		}

		list()
		{
			empty_init();
		}

		list(list<T>& x)
		{
			empty_init();
			for (const auto& e : x)
			{
				Push_back(e);
			}
		}

		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

		void swap(list<T>& x)
		{
			std::swap(_head,x._head);
		}

		list<T>& operator=(list<T> x)
		{
			//if (this != &x)
			//{
			//	clear();
			//	for (const auto& e : x)
			//	{
			//		Push_back(e);
			//	}
			//}
			swap(x);
			return *this;
		}

		void Push_back(const T& x)
		{
			//Node* NewNode = new Node(x);
			//Node* tail = _head->prev;

			//tail->next = NewNode;
			//NewNode->prev = tail;
			//_head->prev = NewNode;
			//NewNode->next = _head;
			insert(_head,x);

		}

		void Push_front(const T& x)
		{
		
			insert(_head->next, x);
		}

		void Pop_back()
		{
			erase(_head->prev);
		}

		void Pop_front()
		{
			erase(_head->next);
		}

		iterator insert(iterator pos, const T& x)
		{
			Node* NewNode = new Node(x);
			Node* cur = pos._node;
			Node* prev = cur->prev;

			NewNode->prev = prev;
			NewNode->next = cur;
			prev->next = NewNode;
			cur->prev = NewNode;

			return NewNode;
		}

		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* del = pos._node;
			Node* delprev = del->prev;
			Node* delnext = del->next;
			delete del;

			delprev->next = delnext;
			delnext->prev = delprev;
			return delnext;
		}

	private:
		Node* _head;
	};

	void print_list(const list<int>& s)
	{
		for (const auto& e : s)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test()
	{
		list<int> v;
		v.Push_back(10);
		v.Push_back(20);
		v.Push_back(30);
		v.Push_back(40);

		list<int> v2;
		v2.Push_back(1);
		v2.Push_back(2);
		v2.Push_back(3);
		v2.Push_back(4);

		v = v2;
		for (auto e : v)
		{
			cout << e << " ";
		}
		
	}

	//void test()
	//{
	//	list<int> v;
	//	v.Push_back(10);
	//	v.Push_back(20);
	//	v.Push_back(30);
	//	v.Push_back(40);
	//	//v.Push_front(555555);
	//	list<int> x(v);


	//	for (auto e : x)
	//	{
	//		cout << e << " ";
	//	}

	//	//list<int>::iterator it = v.begin();
	//	//while (it != v.end())
	//	//{
	//	//	cout << *it << " ";
	//	//	++it;
	//	//}
	//	//cout << endl;

	//	//v.Pop_back();

	//	//for (auto e : v)
	//	//{
	//	//	cout << e << " ";
	//	//}
	//	//cout << endl;

	//	//v.Pop_front();

	//	//for (auto e : v)
	//	//{
	//	//	cout << e << " ";
	//	//}
	//	//cout << endl;

	//	//v.clear();
	//	//for (auto e : v)
	//	//{
	//	//	cout << e << " ";
	//	//}
	//	//cout << endl;

	//	//v.Push_back(10);
	//	//v.Push_back(20);

	//	//for (auto e : v)
	//	//{
	//	//	cout << e << " ";
	//	//}
	//	//cout << endl;
	//}
}



